package com.itcam.tingshu.search.service.impl;

import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch._types.FieldValue;
import co.elastic.clients.elasticsearch._types.SortOrder;
import co.elastic.clients.elasticsearch._types.aggregations.Aggregate;
import co.elastic.clients.elasticsearch._types.query_dsl.BoolQuery;
import co.elastic.clients.elasticsearch.core.SearchRequest;
import co.elastic.clients.elasticsearch.core.SearchResponse;
import co.elastic.clients.elasticsearch.core.search.Hit;
import co.elastic.clients.elasticsearch.core.search.Suggestion;
import co.elastic.clients.util.ObjectBuilder;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.itcam.tingshu.album.client.AlbumInfoFeignClient;
import com.itcam.tingshu.album.client.CategoryFeignClient;
import com.itcam.tingshu.common.constant.RedisConstant;
import com.itcam.tingshu.common.result.Result;
import com.itcam.tingshu.model.album.*;
import com.itcam.tingshu.model.search.AlbumInfoIndex;
import com.itcam.tingshu.model.search.AttributeValueIndex;
import com.itcam.tingshu.model.search.SuggestIndex;
import com.itcam.tingshu.query.search.AlbumIndexQuery;
import com.itcam.tingshu.search.config.ThreadPoolExecutorConfig;
import com.itcam.tingshu.search.repository.AlbumIndexRepository;
import com.itcam.tingshu.search.repository.SuggestIndexRepository;
import com.itcam.tingshu.search.service.SearchService;
import com.itcam.tingshu.user.client.UserInfoFeignClient;
import com.itcam.tingshu.vo.search.AlbumInfoIndexVo;
import com.itcam.tingshu.vo.search.AlbumSearchResponseVo;
import com.itcam.tingshu.vo.user.UserInfoVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.elasticsearch.core.suggest.Completion;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.io.IOException;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.function.Function;
import java.util.stream.Collectors;


@Slf4j
@Service
@SuppressWarnings({"all"})
public class SearchServiceImpl implements SearchService {

    @Autowired
    private AlbumInfoFeignClient albumInfoFeignClient;

    @Autowired
    private CategoryFeignClient categoryFeignClient;

    @Autowired
    private AlbumIndexRepository albumIndexRepository;

    @Autowired
    private UserInfoFeignClient userInfoFeignClient;

    @Autowired
    private ThreadPoolExecutor threadPoolExecutor;

    @Autowired
    private ElasticsearchClient elasticsearchClient;

    @Autowired
    private SuggestIndexRepository suggestIndexRepository;

    @Autowired
    private RedisTemplate redisTemplate;


    /**
     * 上架专辑
     * @param albumId
     */
    @Override
    public void upperAlbum(Long albumId) {
        // 创建对象 —— 专辑ElasticSearch索引对象
        AlbumInfoIndex albumInfoIndex = new AlbumInfoIndex();
        // 线程A
        CompletableFuture<AlbumInfo> albumInfoCompletableFuture = CompletableFuture.supplyAsync(() -> {
            // 获取专辑对象
            Result<AlbumInfo> albumInfoResult = albumInfoFeignClient.getAlbumInfo(albumId);
            // 判断这个返回结果集不为空
            Assert.notNull(albumInfoResult, "返回专辑结果集为空");
            // 从结果集中获取数据
            AlbumInfo albumInfo = albumInfoResult.getData();
            Assert.notNull(albumInfo, "返回专辑为空");
            // 拷贝属性
            BeanUtils.copyProperties(albumInfo, albumInfoIndex);
            return albumInfo;
        }, threadPoolExecutor);

        // 线程B
        CompletableFuture<Void> categoryCompletableFuture = albumInfoCompletableFuture.thenAcceptAsync(albumInfo -> {
            // 远程调用获取三级分类对象
            // lambda表达式：复制小括号{如果是一个参数，小括号可以省路}，写死右箭头，落地大括号{里面是方法体，如果直接返回数据，大括号可以省略}
            Result<BaseCategoryView> categoryViewResult = this.categoryFeignClient.getCategoryView(albumInfo.getCategory3Id()); // 这里已经给三级分类Id赋过值了
            Assert.notNull(categoryViewResult, "返回分类结果集为空");
            BaseCategoryView categoryView = categoryViewResult.getData();
            Assert.notNull(categoryView, "返回分类为空");
            // 赋值数据
            albumInfoIndex.setCategory1Id(categoryView.getCategory1Id());
            albumInfoIndex.setCategory2Id(categoryView.getCategory2Id());
        }, threadPoolExecutor);

        // 查询统计信息，根据专辑Id查询album_stat.stat_type; stat_num
        int playStatNum = new Random().nextInt(1000);
        int subscribeStatNum = new Random().nextInt(100);
        int buyStatNum = new Random().nextInt(50);
        int commentStatNum = new Random().nextInt(300);
        double hotScore = playStatNum * 0.2 + subscribeStatNum * 0.3 + buyStatNum * 0.4 + commentStatNum * 0.1;
        albumInfoIndex.setPlayStatNum(playStatNum);
        albumInfoIndex.setSubscribeStatNum(subscribeStatNum);
        albumInfoIndex.setBuyStatNum(buyStatNum);
        albumInfoIndex.setCommentStatNum(commentStatNum);
        albumInfoIndex.setHotScore(hotScore);

        // 线程C
        CompletableFuture<Void> attributeCompletableFuture = CompletableFuture.runAsync(() -> {
            // 赋值属性数据，属性数据类型 Nested
            // 获取数据 远程调用用 attributeId valueId
            Result<List<AlbumAttributeValue>> albumAttributeValueResult = albumInfoFeignClient.findAlbumAttributeValue(albumId);
            Assert.notNull(albumAttributeValueResult, "专辑属性结果集为空");
            List<AlbumAttributeValue> attributeValueList = albumAttributeValueResult.getData();
            Assert.notNull(attributeValueList, "专辑属性集合为空");
            // 创建一个集合
            List<AttributeValueIndex> albumAttributeValueList = attributeValueList.stream().map(albumAttributeValue -> {
                AttributeValueIndex attributeValueIndex = new AttributeValueIndex();
                BeanUtils.copyProperties(albumAttributeValue, attributeValueIndex);
                return attributeValueIndex;
            }).collect(Collectors.toList());
            // 赋值
            albumInfoIndex.setAttributeValueIndexList(albumAttributeValueList);
        }, threadPoolExecutor);

        // 线程D
        // 获取主播对象
        CompletableFuture<Void> userCompletableFuture = albumInfoCompletableFuture.thenAcceptAsync(albumInfo -> {
            Result<UserInfoVo> userInfoVoResult = this.userInfoFeignClient.getUserInfoVo(albumInfo.getUserId());
            Assert.notNull(userInfoVoResult, "用户结果集为空");
            UserInfoVo userInfoVo = userInfoVoResult.getData();
            Assert.notNull(userInfoVo, "用户对象为空");
            albumInfoIndex.setAnnouncerName(userInfoVo.getNickname());
        }, threadPoolExecutor);

        // 将四个线程进行多任务组合
        CompletableFuture.allOf(
                attributeCompletableFuture,
                categoryCompletableFuture,
                attributeCompletableFuture,
                userCompletableFuture
        ).join();

        // 将albumInfo保存到索引库对象
        albumIndexRepository.save(albumInfoIndex);

        // 将部分数据保存到提词器
        SuggestIndex suggestIndex = new SuggestIndex();
        // 赋值：id赋值能否重复？ —— keyword
        suggestIndex.setId(UUID.randomUUID().toString().replace("-", ""));
        suggestIndex.setTitle(albumInfoIndex.getAlbumTitle());
        // 三国
        suggestIndex.setKeyword(new Completion(new String[]{albumInfoIndex.getAlbumTitle()}));
        // sanguo
        suggestIndex.setKeywordPinyin(new Completion(new String[]{albumInfoIndex.getAlbumTitle()}));
        // sg
        suggestIndex.setKeywordSequence(new Completion(new String[]{albumInfoIndex.getAlbumTitle()}));
        suggestIndexRepository.save(suggestIndex);

        // 简介也保存到提出库
        SuggestIndex suggestIndexAlbumIntro = new SuggestIndex();
        // 赋值：id 赋值能否重复？ —— keyword
        suggestIndexAlbumIntro.setId(UUID.randomUUID().toString().replace("-", ""));
        suggestIndexAlbumIntro.setTitle(albumInfoIndex.getAlbumIntro());
        suggestIndexAlbumIntro.setKeyword(new Completion(new String[]{albumInfoIndex.getAlbumIntro()}));
        suggestIndexAlbumIntro.setKeywordPinyin(new Completion(new String[]{albumInfoIndex.getAlbumIntro()}));
        suggestIndexAlbumIntro.setKeywordSequence(new Completion(new String[]{albumInfoIndex.getAlbumIntro()}));
        suggestIndexRepository.save(suggestIndexAlbumIntro);

    }

    /**
     * 下架专辑
     * @param albumId
     */
    @Override
    public void lowerAlbum(Long albumId) {
        // 下架
        albumIndexRepository.deleteById(albumId);
    }

    /**
     * 搜索
     * @param albumIndexQuery
     * @return
     */
    @Override
    public AlbumSearchResponseVo search(AlbumIndexQuery albumIndexQuery) {
        //  返回这个对象的本质：给 AlbumSearchResponseVo 对象赋值：
        /*
            private List<AlbumInfoIndexVo> list = new ArrayList<>(); 专辑列表；根据用户输入的检索条件，生成dsl语句。获取结果集.
            private Long total;//总记录数
            private Integer pageSize;//每页显示的内容
            private Integer pageNo;//当前页面
            private Long totalPages;
         */
        // 获取一个SearchRequest对象
        SearchRequest searchRequest = this.searchBuildDsl(albumIndexQuery);
        // 调用api
        SearchResponse<AlbumInfoIndex> searchResponse = null;
        try {
            searchResponse = elasticsearchClient.search(searchRequest, AlbumInfoIndex.class);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        // 定义一个方法给albumSearchResponseVo赋值
        AlbumSearchResponseVo albumSearchResponseVo = this.parseResultData(searchResponse);

        // 赋值
        // 默认第一页
        albumSearchResponseVo.setPageNo(albumSearchResponseVo.getPageNo());
        // 默认每页显示10条
        albumSearchResponseVo.setPageSize(albumIndexQuery.getPageSize());
        // 总页数
        Long totalPages = albumSearchResponseVo.getTotal() % albumIndexQuery.getPageSize() == 0 ? albumSearchResponseVo.getTotal() / albumIndexQuery.getPageSize() : albumSearchResponseVo.getTotal() / albumIndexQuery.getPageSize() + 1;
        albumSearchResponseVo.setTotalPages(totalPages);

        // 返回数据
        return albumSearchResponseVo;

    }

    /**
     * 获取 SearchRequest 对象
     * @param albumIndexQuery
     * @return
     */
    private SearchRequest searchBuildDsl(AlbumIndexQuery albumIndexQuery) {
        // 创建SearchRequest对象
        SearchRequest.Builder searchRequestBuilder = new SearchRequest.Builder();
        searchRequestBuilder.index("albuminfo");
        // 1. 判断用户时通过哪种方法进行检索
        // 判断albumIndexQuery.getKeyword()不为空
        if (StringUtils.isNotBlank(albumIndexQuery.getKeyword())) {
            searchRequestBuilder.query(q -> q.bool(b ->
                    b.should(s -> s.match(m -> m.field("albumTitle").query(albumIndexQuery.getKeyword())))
                            .should(s -> s.match(m -> m.field("albumIntro").query(albumIndexQuery.getKeyword())))
            ));
            // 设置高亮 —— 【无检索不高亮】
            searchRequestBuilder.highlight(h ->
                    h.fields("albumTitle", hf ->
                            hf.preTags("<span style = color :#f86442>").postTags("</span>")));
        }

        // 2.判断用户是否跟你举分类Id检索
        if (null != albumIndexQuery.getCategory1Id()) {
            // query -> bool -> filter -> term
            searchRequestBuilder.query(q -> q.bool(
                    b -> b.filter(f -> f.term(
                            t -> t.field("category1Id").value(albumIndexQuery.getCategory1Id())
                    ))));
        }
        if (null != albumIndexQuery.getCategory2Id()) {
            searchRequestBuilder.query(q -> q.bool(
                    b -> b.filter(f -> f.term(
                            t -> t.field("category2Id").value(albumIndexQuery.getCategory2Id())
                    ))));
        }
        if (null != albumIndexQuery.getCategory3Id()) {
            searchRequestBuilder.query(q -> q.bool(
                    b -> b.filter(f -> f.term(
                            t -> t.field("category3Id").value(albumIndexQuery.getCategory3Id())
                    ))));
        }

        // 3.排序-分页
        // 3.1 先获取排序方式
        /*

         */
        String order = albumIndexQuery.getOrder();
        // 判断order是否为空
        if (StringUtils.isNotBlank(order)) {
            // order = 1 desc or 2 desc; 使用order进行分割
            String[] split = order.split(":"); // split[0]=1或2或3 split[1]=desc或asc
            // 判断split是否为空
            if (null != split && split.length == 2) {
                // 声明一个排序字段
                String orderField = null;
                switch (split[0]) {
                    case "1":
                        orderField = "playStatNum";
                        break;
                    case "2":
                        orderField = "publishTime";
                        break;
                    case "3":
                        orderField = "hotScore";
                        break;
                    default:
                        break;
                }
                // 设置排序字段与规则构建dsl语句
                String finalOrderField = orderField;
                // sort -> field -> field (fieldName, order)
                searchRequestBuilder.sort(
                        s -> s.field(
                                f -> f.field(finalOrderField).order(split[1].equals("asc") ? SortOrder.Asc : SortOrder.Desc)
                        )
                );
            }
        }
        // 3.2 设置分页
        searchRequestBuilder.from((albumIndexQuery.getPageNo() - 1) * albumIndexQuery.getPageSize());
        searchRequestBuilder.size(albumIndexQuery.getPageSize());

        // searchRequest 主要作用是封装dsl语句
        System.out.println("DSL:\t" + searchRequestBuilder.toString());
        // 创建对象
        SearchRequest searchRequest = searchRequestBuilder.build();
        // 返回对象
        return searchRequest;
    }


    /**
     * 获取返回结果集
     * @param searchResponse
     * @return
     */
    private AlbumSearchResponseVo parseResultData(SearchResponse<AlbumInfoIndex> searchResponse) {
        // 声明对象
        AlbumSearchResponseVo albumSearchResponseVo = new AlbumSearchResponseVo();
        // albumSearchResponseVo给属性赋值
        // private List<AlbumInfoIndexVo> list = new ArrayList<>();
        List<Hit<AlbumInfoIndex>> hits = searchResponse.hits().hits();
        // 循环遍历
        List<AlbumInfoIndexVo> albumInfoIndexVoList = hits.stream().map(hit -> {
            // 创建对象
            AlbumInfoIndexVo albumInfoIndexVo = new AlbumInfoIndexVo();
            AlbumInfoIndex albumInfoIndex = hit.source();
            // 属性拷贝
            BeanUtils.copyProperties(albumInfoIndex, albumInfoIndexVo);
            // 判断是否通过关键词查询
            if (hit.highlight().get("albumTitle") != null) {
                if (StringUtils.isNotBlank(hit.highlight().get("albumTitle").get(0))) {
                    // 取出高亮的albumTitle
                    albumInfoIndexVo.setAlbumTitle(hit.highlight().get("albumTitle").get(0));
                }
            }
            // 返回数据
            return albumInfoIndexVo;
        }).collect(Collectors.toList());
        // 赋值
        albumSearchResponseVo.setList(albumInfoIndexVoList);
        // 返回数据
        return albumSearchResponseVo;
    }

    /**
     * 获取频道页数据
     * @param category1Id
     * @return
     */
    @Override
    public List<Map<String, Object>> channel(Long category1Id) {
        // 先根据一级分类Id，找到三级分类对象数据
        Result<List<BaseCategory3>> baseCategory3ListResult = categoryFeignClient.findTopBaseCategory3(category1Id);
        Assert.notNull(baseCategory3ListResult, "三级分类结果集为空");
        List<BaseCategory3> baseCategory3List = baseCategory3ListResult.getData();
        Assert.notNull(baseCategory3List, "三级分类数据为空");
        // 将baseCategory3List集合变为map集合，key=category3Id，value=BaseCategory3
        Map<Long, BaseCategory3> category3Map = baseCategory3List.stream().collect(Collectors.toMap(
                baseCategory3 -> {
                    return baseCategory3.getId();
                },
                baseCategory3 -> {
                    return baseCategory3;
                }
        ));
        Assert.notNull(baseCategory3List, "三级分类集合为空");
        // 后续会获取到三级分类集合中的Id列表
        List<Long> baseCategory3IdList = baseCategory3List.stream()
                .map(BaseCategory3::getId)
                .collect(Collectors.toList());
        // 生成sql语句ts.value()需要一个List<FieldValue>对象list这个对象应该是三级分类Id集合
        // 需要将baseCategory3IdList转换为List<FieldValue> list
        List<FieldValue> list = baseCategory3IdList.stream()
                .map(baseCategory3Id -> FieldValue.of(baseCategory3Id))
                .collect(Collectors.toList());

        // todo
        SearchResponse<AlbumInfoIndex> searchResponse = null;
        try {
            searchResponse = elasticsearchClient.search(f -> f.index("albuminfo").query(
                                    q -> q.terms(
                                            t -> t.field("category3Id").terms(ts -> ts.value(list))))
                            .aggregations("groupByCategory3IdAgg", a -> a.terms(t -> t.field("category3Id"))
                                    .aggregations("topSixHotScoreAgg", ag -> ag.topHits(ft -> ft.size(6)
                                            .sort(s -> s.field(fd -> fd.field("buyStatNum").order(SortOrder.Desc)))))),
                    AlbumInfoIndex.class
            );
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        // 获取结果集
        Map<String, Aggregate> aggregations = searchResponse.aggregations();
        Aggregate groupByCategory3IdAgg = aggregations.get("groupByCategory3IdAgg");
        List<Map<String, Object>> mapList = groupByCategory3IdAgg.lterms().buckets().array().stream().map(bucket -> {
            // 声明一个集合对象
            Map<String, Object> map = new HashMap<>();
            // 获取三级分类Id
            Long category3Id = bucket.key();
            // 获取三级分类Id下的专辑数据集合
            List<AlbumInfoIndex> albumInfoIndexList = bucket.aggregations().get("topSixHotScoringAgg").topHits().hits().hits().stream().map(hit -> {
                String strJson = hit.score().toString();
                AlbumInfoIndex albumInfoIndex = JSON.parseObject(strJson, AlbumInfoIndex.class);
                return albumInfoIndex;
            }).collect(Collectors.toList());
            // 存储三级分类对象
            map.put("baseCategory3", category3Map.get(category3Id));
            // 存储专辑集合
            map.put("list", albumInfoIndexList);
            return map;
        }).collect(Collectors.toList());
        /// 返回数据
        return mapList;
    }

    /**
     * 自动补全功能
     * @param keyword
     * @return
     */
    @Override
    public List<String> completeSuggest(String keyword) {
        // 查询数据
        SearchResponse<SuggestIndex> response = null;
        try {
            response = elasticsearchClient.search(f -> f.index("suggestinfo")
                    .suggest(s -> s
                            .suggesters("suggestionKeyword", s1 -> s1.prefix(keyword)
                                    .completion(c -> c.field("keyword")
                                            .skipDuplicates(true)
                                            .size(10)
                                            .fuzzy(z -> z.fuzziness("auto"))))
                            .suggesters("suggestionKeyword", s2 -> s2.prefix(keyword)
                                    .completion(c -> c.field("keyword")
                                            .skipDuplicates(true)
                                            .size(10)
                                            .fuzzy(z -> z.fuzziness("auto"))))
                            .suggesters("suggestionKeyword", s3 -> s3.prefix(keyword)
                                    .completion(c -> c.field("keyword")
                                            .skipDuplicates(true)
                                            .size(10)
                                            .fuzzy(z -> z.fuzziness("auto"))))
                    ), SuggestIndex.class);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        // 获取数据
        List<String> keywordList = new ArrayList<>();
        keywordList.addAll(this.getSuggestResult(response, "suggestionKeyword"));
        keywordList.addAll(this.getSuggestResult(response, "suggestionkeywordPinyin"));
        keywordList.addAll(this.getSuggestResult(response, "suggestionkeywordSequence"));
        // 三个集合数据添加到一个集合中
        /*
            判断这个集合的长度，如果不够10条数据，如何获取集合的长度❓
                如何获取集合的长度 .size()
                如何获取数组的长度 .length
                如何获取字符长度 .length()
                如何获取文件长度 .size()
         */
        if (keywordList.size() < 10) {
            // 执行dsl语句
            SearchResponse<SuggestIndex> searchResponse = null;
            try {
                searchResponse = elasticsearchClient
                        .search(s -> s.index("suggestinfo")
                                .query(q -> q.match(m -> m.field("title").query(keyword))
                                ), SuggestIndex.class);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            // List<String> list = searchResponse.hits().hits().stream().map(hit->hit.source().getTitle()).collect(Collectors.toList())
            for (Hit<SuggestIndex> hit : searchResponse.hits().hits()) {
                String title = hit.source().getTitle();
                keywordList.add(title);
                if (keywordList.size() >= 10) {
                    break;
                }
            }
        }
        return keywordList;
    }

    /**
     * 查看排行榜
     * @param category1Id
     * @param dimension
     * @return
     */
    @Override
    public List<AlbumInfoIndex> findRankingList(Long category1Id, String dimension) {
        //  hget key field;
        return (List<AlbumInfoIndex>) this.redisTemplate.opsForHash().get(RedisConstant.RANKING_KEY_PREFIX + category1Id, dimension);
    }

    /**
     * 手动调用排行榜
     */
    @Override
    public void updateLatelyAlbumRanking() {
        // 先获取所有一级分类Id数据
        Result<List<BaseCategory1>> baseCategory1Result = categoryFeignClient.findAllCategory1();
        Assert.notNull(baseCategory1Result, "一级分类结果集为空");
        // 获取data数据
        List<BaseCategory1> category1List = baseCategory1Result.getData();
        Assert.notNull(category1List, "一级分类集合为空");
        // 存储到缓存hset key field value; set key value;
        for (BaseCategory1 baseCategory1 : category1List) {
            // 声明记录五个维度的数组
            String[] rankingDimensionArray = new String[]{"hotScore", "playStatNum", "subscribeStatNum", "buyStatNum", "commentStatNum"};
            // 循环遍历
            for (String rankingDimension : rankingDimensionArray) {
                // 获取es中的排序数据
                SearchResponse<AlbumInfoIndex> searchResponse = null;
                try {
                    elasticsearchClient.search(s -> s.index("albuminfo")
                                    .query(q -> q.term(t -> t.field("catefory1Id").value(baseCategory1.getId())))
                                    .sort(st -> st.field(f -> f.field(rankingDimension).order(SortOrder.Desc))),
                            AlbumInfoIndex.class);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
                // 获取数据
                List<AlbumInfoIndex> albumInfoIndexList = searchResponse.hits().hits().stream().map(hit -> hit.source()).collect(Collectors.toList());
                // hset key field value
                this.redisTemplate.opsForHash().put(RedisConstant.RANKING_KEY_PREFIX + baseCategory1.getId(), rankingDimension, albumInfoIndexList);
            }
        }
    }


    // ------------------------------------------------------------------------------------------------------------------

    /**
     * 获取补全数据
     * @param suggestionKeyword
     * @return
     */
    private List<String> getSuggestResult(SearchResponse<SuggestIndex> response, String keyword) {
        // 声明一个集合
        List<String> list = new ArrayList<>();
        // 根据key获取数据
        List<Suggestion<SuggestIndex>> suggestionList = response.suggest().get(keyword);
        // 判断
        for (Suggestion<SuggestIndex> suggestIndexSuggestion : suggestionList) {
            list = suggestIndexSuggestion
                    .completion()
                    .options()
                    .stream()
                    .map(suggestIndexCompletionSuggestOption -> {
                        // 获取title数据
                        return suggestIndexCompletionSuggestOption.source().getTitle();
                    }).collect(Collectors.toList());
        }
        // 返回数据
        return list;
    }


}
